home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 2.0.1 / MacApp CD Release / MacApp 2.0.1 (Hard Disk Ready) / Libraries / UMacApp.Globals.p < prev    next >
Text File  |  1990-10-25  |  45KB  |  1,777 lines

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { UMacApp.Globals.p }
  4. { Copyright © 1984-1990 by Apple Computer Inc. All rights reserved. }
  5.  
  6. PROCEDURE InitializationThatMustNotFail;
  7.     FORWARD;
  8.  
  9. PROCEDURE DoInitUMacApp;
  10.     FORWARD;
  11.  
  12. {--------------------------------------------------------------------------------------------------}
  13. {$S MAGlobalsRes}
  14.  
  15. PROCEDURE ApplicationBeep;
  16.  
  17.     BEGIN
  18.     IF gApplication <> NIL THEN
  19.         gApplication.Beep(2)
  20.     ELSE
  21.         SysBeep(2);
  22.     END;
  23.  
  24. {--------------------------------------------------------------------------------------------------}
  25. {$S MAGlobalsRes}
  26.  
  27. PROCEDURE CanPaste(aClipType: ResType);
  28.  
  29.     BEGIN
  30.     IF gClipView <> NIL THEN
  31.         IF gClipView.ContainsClipType(aClipType) THEN
  32.             BEGIN
  33.             gGotClipType := TRUE;
  34.             gPrefClipType := aClipType;
  35.             END;
  36.     END;
  37.  
  38. {--------------------------------------------------------------------------------------------------}
  39. {$S MAGlobalsRes}
  40. {$Push} {$IFC qTrace} {$D+} {$EndC}
  41.  
  42. PROCEDURE CleanupMacApp;
  43.  
  44.     VAR
  45.         OldA5:                LongInt;
  46.  
  47.     BEGIN
  48.     OldA5 := SetCurrentA5;                                { ***** Called from trap patches *****}
  49.  
  50.     { Make sure segments can load }
  51.     SetResLoad(TRUE);
  52.     IF PermAllocation(FALSE) THEN;
  53.  
  54.     UnpatchTrap(pETSPatch);                             { Guaranteed not to fail }
  55.  
  56.     IF gApplication <> NIL THEN
  57.         gApplication.Terminate;
  58.  
  59.     BusyRemove;
  60.  
  61.     {$IFC qDebug}
  62.     DebugTerminate;
  63.     {$ENDC}
  64.  
  65.     UnpatchAll;
  66.  
  67.     IF SetChooserAlert(gOldChooserFlag) THEN;
  68.  
  69.     OldA5 := SetA5(OldA5);
  70.     END;
  71. {$Pop}
  72.  
  73. {--------------------------------------------------------------------------------------------------}
  74. {$S MAGlobalsRes}
  75.  
  76. PROCEDURE DoneViewRsrc(viewRsrc: UNIV Handle;
  77.                        lastPtr: UNIV LongInt);
  78.  
  79.     BEGIN
  80.     HUnlock(viewRsrc);
  81.     SetPermHandleSize(viewRsrc, StripLong(lastPtr) - StripLong(viewRsrc^));
  82.     END;
  83.  
  84. {--------------------------------------------------------------------------------------------------}
  85. {$IFC qDebug}
  86. {$S MADebug}
  87. {$Push} {$IFC qTrace} {$D+} {$ENDC}
  88.  
  89. PROCEDURE DoneWithTempRgn;
  90.  { Indicates that gTempRgn is no longer in use. Call this only if qDebug
  91.   is true. }
  92.  
  93.     BEGIN
  94.     IF NOT gBusyTempRgn THEN
  95.         ProgramBreak('DoneWithTempRgn called, but gTempRgn is not locked');
  96.     gBusyTempRgn := FALSE;
  97.     gUsedBy := '';
  98.     SetEmptyRgn(gTempRgn);
  99.     END;
  100. {$Pop}
  101. {$ENDC}
  102.  
  103. {--------------------------------------------------------------------------------------------------}
  104. {$IFC qDebug}
  105. {$S MADebug}
  106.  
  107. PROCEDURE EntDebugger(entering: BOOLEAN);
  108.  
  109.     BEGIN
  110.     BusyActivate(NOT entering);
  111.     END;
  112. {$ENDC}
  113.  
  114. {--------------------------------------------------------------------------------------------------}
  115. {$S MAError}
  116.  
  117. PROCEDURE ErrorAlert(err: OSErr;
  118.                      message: LongInt);
  119.  
  120.     CONST
  121.         kMsgCmdErr            = msgCmdErr DIV $10000;
  122.         kMsgAlert            = msgAlert DIV $10000;
  123.         kMsgLookup            = msgLookup DIV $10000;
  124.         kMsgAltRecov        = msgAltRecovery DIV $10000;
  125.  
  126.     TYPE
  127.         Converter            = RECORD
  128.             CASE BOOLEAN OF
  129.                 TRUE:
  130.                     (message:             LongInt);
  131.                 FALSE:
  132.                     (hiWd, loWd:         INTEGER);
  133.             END;
  134.  
  135.     VAR
  136.         c:                    Converter;
  137.         alertID:            INTEGER;
  138.         genericAlert:        BOOLEAN;
  139.         opString:            Str255;
  140.         errStr:             Str255;
  141.         recovErr:            OSErr;
  142.         recovery:            Str255;
  143.         x:                    BOOLEAN;
  144.  
  145.     BEGIN
  146.     c.message := message;
  147.  
  148.     alertID := phGenError;                                { the default alert }
  149.     genericAlert := TRUE;
  150.     opString := '';
  151.  
  152.     CASE c.hiWd OF
  153.         kMsgCmdErr:
  154.             BEGIN
  155.             alertID := phCmdErr;
  156.             CmdToName(c.loWd, opString);
  157.             END;
  158.         kMsgAlert:
  159.             BEGIN
  160.             alertID := c.loWd;
  161.             genericAlert := FALSE;
  162.             END;
  163.         kMsgLookup, kMsgAltRecov:
  164.             BEGIN
  165.             x := LookupErrString(c.loWd, errOperationsID, opString);
  166.             END;
  167.         OTHERWISE
  168.             BEGIN
  169.             GetIndString(opString, c.hiWd, c.loWd);
  170.             END;
  171.     END;
  172.  
  173.     IF genericAlert THEN
  174.         BEGIN
  175.         x := LookupErrString(err, errReasonID, errStr);
  176.  
  177.         IF c.hiWd = kMsgAltRecov THEN
  178.             recovErr := c.loWd
  179.         ELSE
  180.             recovErr := err;
  181.  
  182.         x := LookupErrString(recovErr, errRecoveryID, recovery);
  183.  
  184.         ParamText(errStr, recovery, opString, gErrorParm3);
  185.  
  186.         IF opString = '' THEN
  187.             alertID := phUnknownErr;
  188.         END;
  189.  
  190.     StdAlert(alertID);
  191.     gInhibitNestedHandling := FALSE;                    { Used suppress nested event handling }
  192.  
  193.     IF genericAlert THEN
  194.         ResetAlrtStage;
  195.     END;
  196.  
  197. {--------------------------------------------------------------------------------------------------}
  198. {$S MATerminate}
  199.  
  200. PROCEDURE ExitMacApp;
  201.  
  202.     BEGIN
  203.     CleanupMacApp;
  204.     ExitToShell;
  205.     END;
  206.  
  207. {--------------------------------------------------------------------------------------------------}
  208. {$S MAGlobalsRes}
  209.  
  210. FUNCTION ExpandPtr(viewRsrc: UNIV Handle;
  211.                    VAR p: UNIV LongInt;
  212.                    offset: LongInt): Ptr;
  213.  
  214.     VAR
  215.         oldOffset:            LongInt;
  216.         rsrcSize:            Size;
  217.         desiredEnd:         LongInt;
  218.         rsrcBase:            LongInt;
  219.         currentPtr:         LongInt;
  220.  
  221.     BEGIN
  222.     rsrcSize := GetHandleSize(viewRsrc);
  223.     rsrcBase := StripLong(viewRsrc^);
  224.     currentPtr := StripLong(p);
  225.     IF ODD(offset) THEN
  226.         offset := offset + 1;
  227.     desiredEnd := currentPtr + offset + SIZEOF(INTEGER);
  228.  
  229.     IF desiredEnd >= rsrcBase + rsrcSize THEN
  230.         BEGIN
  231.   { This appropriation logic might need some re-examination.  If the size of the added
  232.    template is larger than the minimum amount, then simply the size is added.  If
  233.    the handle is already near to being full, this won't help for the next allocation.
  234.    Maybe it should use a hystersis?… }
  235.         oldOffset := currentPtr - rsrcBase;
  236.         HUnlock(viewRsrc);
  237.         SetHandleSize(viewRsrc, rsrcSize + MAX(kViewRsrcExpandAmt, offset));
  238.         FailMemError;
  239.         LockHandleHigh(viewRsrc);
  240.         p := LongInt(viewRsrc^) + oldOffset;
  241.         END;
  242.     ExpandPtr := Ptr(p);
  243.     OffsetPtr(p, offset);
  244.     END;
  245.  
  246. {--------------------------------------------------------------------------------------------------}
  247. {$S MAGlobalsRes}
  248.  
  249. FUNCTION ExpandPtrWStr(viewRsrc: UNIV Handle;
  250.                        VAR p: UNIV LongInt;
  251.                        offset, len: LongInt): Ptr;
  252.  
  253.     BEGIN
  254.     ExpandPtrWStr := ExpandPtr(viewRsrc, p, offset - 255 + len);
  255.     END;
  256.  
  257. {--------------------------------------------------------------------------------------------------}
  258. {$S MAFinder}
  259. { This is a dummy procedure to allow us to find the Finder segment }
  260.  
  261. PROCEDURE FinderSegProc;
  262.  
  263.     BEGIN
  264.     END;
  265.  
  266. {--------------------------------------------------------------------------------------------------}
  267. {$S MAGlobalsRes}
  268.  
  269. FUNCTION FreeIfWMgrWindow(w: WindowPtr;
  270.                          dispose: BOOLEAN): WindowPtr;
  271.  
  272.     BEGIN
  273.     FreeIfWMgrWindow := NIL;    { convenience to caller }
  274.  
  275.     IF w <> NIL THEN
  276.         BEGIN
  277.         IF dispose THEN
  278.             BEGIN
  279.             IF w = thePort THEN                         { Only need to invalidate focus if freed
  280.                                                          window is the current port }
  281.                 BEGIN
  282.                 IF gApplication <> NIL THEN
  283.                     gApplication.InvalidateFocus;
  284.                 SetPort(gWorkPort);
  285.                 END;
  286.             DisposeWindow(w);
  287.             END
  288.         ELSE
  289.             CloseWindow(w);
  290.         END;
  291.     END;
  292.  
  293. {--------------------------------------------------------------------------------------------------}
  294. {$S MAGlobalsRes}
  295.  
  296. PROCEDURE FreeWMgrWindow(w: WindowPtr;
  297.                          dispose: BOOLEAN);
  298.  
  299.     BEGIN
  300.     w := FreeIfWMgrWindow(w, dispose);
  301.     END;
  302.  
  303. {--------------------------------------------------------------------------------------------------}
  304. {$S MAGlobalsRes}
  305.  
  306. PROCEDURE GetFocus(VAR theFocusRec: FocusRec);
  307.  
  308.     BEGIN
  309.     WITH theFocusRec DO
  310.         BEGIN
  311.         GetPort(Port);
  312.         GetClip(Clip);
  313.         Org := Port^.portRect.topLeft;
  314.         LongOffset := gLongOffset;
  315.         FocusedView := gFocusedView;
  316.         printing := gPrinting;
  317.         drawingPictScrap := gDrawingPictScrap;
  318.         drawingPictScrapView := gDrawingPictScrapView;
  319.         isValid := TRUE;
  320.         END;
  321.     END;
  322.  
  323. {--------------------------------------------------------------------------------------------------}
  324. {$S MAGlobalsRes}
  325.  
  326. FUNCTION GetNewCenteredDialog(dialogID: INTEGER;
  327.                               dStorage: Ptr;
  328.                               behind: WindowPtr): DialogPtr;
  329.  
  330.     VAR
  331.         dlogTemplate:        DialogTHndl;
  332.  
  333.     BEGIN
  334.     GetNewCenteredDialog := NIL;
  335.     SetCursor(arrow);
  336.     IF gApplication <> NIL THEN
  337.         gApplication.InvalidateCursorRgn;
  338.     dlogTemplate := DialogTHndl(GetResource('DLOG', dialogID));
  339.     IF dlogTemplate <> NIL THEN
  340.         BEGIN
  341.         CenterRectOnScreen(dlogTemplate^^.boundsRect, TRUE, TRUE, TRUE);
  342.         GetNewCenteredDialog := GetNewDialog(dialogID, dStorage, behind);
  343.         END
  344.     ELSE
  345.         BEGIN
  346.         SysBeep(2);                                     { At least give some indication }
  347.         {$IFC qDebug}
  348.         ProgramBreak(ConcatNumber('Unable to find ‘DLOG’ resource ', dialogID));
  349.         {$ENDC}
  350.         END;
  351.     END;
  352.  
  353. {--------------------------------------------------------------------------------------------------}
  354. {$S MAUtilitiesRes}{ Really a utility but, the gWorkPort isn't reachable from UMacAppUtilities }
  355.  
  356. PROCEDURE GetTextStyleFontInfo(theTextStyle: TextStyle; VAR theFontInfo: FontInfo);
  357.  
  358.     VAR
  359.         savedPort:    GrafPtr;
  360.  
  361.     BEGIN
  362.     GetPort(savedPort);
  363.     SetPort(gWorkPort);
  364.     SetPortTextStyle(theTextStyle);
  365.     GetFontInfo(theFontInfo);
  366.     SetPort(savedPort);
  367.     END;
  368.  
  369. {--------------------------------------------------------------------------------------------------}
  370. {$S MAGlobalsRes}                                        { Must be in a resident segment so that
  371.                                                          UnloadAllSegments doesn't unload it. }
  372.  
  373. PROCEDURE HdlInitFailed(error: OSErr;
  374.                         message: LongInt);
  375.  
  376.     BEGIN
  377.     UnloadAllSegments;
  378.  
  379.     IF error <> noErr THEN                                { check to see if an alert has already been
  380.                                                          displayed }
  381.         BEGIN
  382.         IF message = 0 THEN
  383.             message := msgInitFailed;                    { if no message specified, use our own }
  384.  
  385.         ErrorAlert(error, message);
  386.  
  387.         ExitToShell;
  388.         END;
  389.     END;
  390.  
  391. {--------------------------------------------------------------------------------------------------}
  392. {$Push}
  393. {$MC68020-}                                             { Must be universal code }
  394. {$S Main}
  395. { Essential one-time initialization }
  396.  
  397. PROCEDURE InitUMacApp(callsToMoreMasters: INTEGER);
  398. { Must be in the Main segment since all other segments get unloaded from here.}
  399.  
  400.     VAR
  401.         initSeg:            INTEGER;
  402.         applZone:            THz;
  403.         oldMoreMast:        INTEGER;
  404.  
  405.     PROCEDURE HdlInitUMacApp(error: OSErr;
  406.                              message: LongInt);
  407.  
  408.         BEGIN
  409.         { try to make a little extra room. }
  410.         UnloadSeg(@InitializationThatMustNotFail);
  411.  
  412.         IF error <> noErr THEN                            { check to see if an alert has already been
  413.                                                          displayed }
  414.             BEGIN
  415.             IF message = 0 THEN
  416.                 message := msgInitFailed;                { if no message specified, use our own }
  417.  
  418.             {$IFC qDebug}
  419.             UnloadSeg(@PLFlush);
  420.             {$ENDC}
  421.  
  422.             ErrorAlert(error, message);
  423.  
  424.             ExitToShell;
  425.             END;
  426.         END;
  427.  
  428.     BEGIN
  429.     IF NOT gToolboxInitialized THEN
  430.         InitToolbox;
  431.  
  432.     IF ValidateConfiguration(gConfiguration) THEN        { Make sure we can run. The programmer really
  433.                                                         should have ensured this in their "M" file but
  434.                                                         this is a backup check just in case.  After
  435.                                                         all 68000's don't really like to RTD.}
  436.         BEGIN
  437.         InitializationThatMustNotFail;
  438.     
  439.         CatchFailures(pFi, HdlInitUMacApp);
  440.         InitUMemory;
  441.     
  442.         { Install Outermost failure handler }
  443.         Success(pFi);
  444.         CatchFailures(pFi, HdlInitFailed);
  445.     
  446.         UnloadAllSegments;
  447.     
  448.         { Here is a trick sugested by Jerome C.--it allocates one large block of master pointers
  449.         ??? Its cute, but will it eventually break? }
  450.         applZone := ApplicZone;
  451.         oldMoreMast := applZone^.moreMast;
  452.         applZone^.moreMast := oldMoreMast * callsToMoreMasters;
  453.         MoreMasters;
  454.         applZone^.moreMast := oldMoreMast;
  455.     
  456.         LoadResidentSegments;
  457.     
  458.         InitUObject;                                        { Initialize runtime support for objects }
  459.     
  460.         {$IFC qInspector}
  461.         InitUInspector;
  462.         {$ENDC}
  463.     
  464.         { Force the init segment to be memory resident, so we can call UnloadAllSegs during init }
  465.         initSeg := GetSegNumber(@DoInitUMacApp);
  466.         SetResidentSegment(initSeg, TRUE);
  467.     
  468.         DoInitUMacApp;                                        { do rest of initialization }
  469.     
  470.         SetResidentSegment(initSeg, FALSE);                 { make it non-resident }
  471.         UnloadAllSegments;
  472.         END
  473.     ELSE
  474.         BEGIN
  475.         StdAlert(phUnsupportedConfiguration);
  476.         ExitToShell;
  477.         END;
  478.     END;
  479. {$Pop}
  480.  
  481. {--------------------------------------------------------------------------------------------------}
  482. {$S MAMiniInit}                                         { Must be in MAMiniInit }
  483.  
  484. PROCEDURE ClearTheFPU;
  485.     INLINE $42A7,                                        { CLR.L -(A7) }
  486.            $42A7,                                        { CLR.L -(A7) }
  487.            $F21F, $9800;                                { FMOVEM (A7)+, FPCR/FPSR }
  488.  
  489. PROCEDURE InitializationThatMustNotFail;
  490. { Nothing in this routine can fail. }
  491.  
  492.     BEGIN
  493.     { the main procedure is always compiled with universal code so, the FPU must be reset before it
  494.     is used.  We could get spurious crashes or worse.
  495.  
  496.     Remember: 2+2=4… every time!
  497.     }
  498.     IF qNeedsFPU | gConfiguration.hasFPU THEN
  499.         ClearTheFPU;
  500.  
  501.     InitUPatch;
  502.  
  503.     {$IFC qDebug}
  504.     gExperimenting := FALSE;
  505.     gDebugPrinting := FALSE;
  506.     gReportMenuChoices := FALSE;
  507.     gIntenseDebugging := FALSE;
  508.     gReportEvt := FALSE;
  509.     gMastReport := FALSE;
  510.     gRsrcReport := FALSE;
  511.     gMemMgtBreak := FALSE;
  512.     {$ENDC}
  513.  
  514.     { the following set up is necessary to call CleanupMacApp }
  515.     gApplication := NIL;
  516.  
  517.  
  518.     gMacAppAlertFilter := NIL;
  519.  
  520.     { !!! The alert filter is pretty good but… its new enough, and changes behaviour enough that
  521.     we are more comfortable NOT installing it by default in this release (2.0).  If you wish
  522.     to use it and are not using the qExperimentalAndUnsupported flag then just assign its address
  523.     into gMacAppAlertFilter in you IYourApplication method. }
  524.  
  525.     {$IFC qExperimentalAndUnsupported}
  526.     gMacAppAlertFilter := @MacAppAlertFilter;
  527.     {$EndC}
  528.  
  529.     gInFilter := FALSE;
  530.     gInhibitNestedHandling := FALSE;                    { Allow nested handling }
  531.     
  532.     {$IFC qExperimentalAndUnsupported}
  533.     gEnableDoubleBuffering := TRUE;
  534.     {$EndC}
  535.  
  536.     FailNil(gCursorRgn);
  537.     END;
  538. {--------------------------------------------------------------------------------------------------}
  539. {$S MAInit}                                             { Must be in the init segment; unloaded at
  540.                                                          start of event loop }
  541.  
  542. PROCEDURE DoInitUMacApp;
  543.  
  544.     VAR
  545.         message:            INTEGER;
  546.         {$IFC qDebug}
  547.         gDebugKeyMap:        KeyMap;                     { the key state at start-up time }
  548.         {$ENDC}
  549.         fontSize, fontNum:            INTEGER;
  550.  
  551.     BEGIN
  552.     InitUBusyCursor;
  553.     FailOsErr(HeadPatch(pETSPatch, _ExitToShell, @CleanupMacApp));
  554.     BusyInstall;
  555.  
  556.     gAlwaysTrackCursor := FALSE;
  557.  
  558.     gMainEventMask := everyEvent;
  559.  
  560.     pCopyright := NewString(kCopyright);
  561.  
  562.     {$IFC qDebug}
  563.     gRsrcCheck := kRsrcCheckInterval;
  564.     gAssumeFocused := TRUE;                             { make TView.AssumeFocused actually check
  565.                                                          focus }
  566.     {$ENDC}
  567.  
  568.     { Other 1-time initialization }
  569.     gTempRgn := MakeNewRgn;
  570.     gSaveFocusRec.Clip := MakeNewRgn;
  571.  
  572.     gClickCount := 0;
  573.     gLastUpTime := TickCount;
  574.     gLastClickPart := inDesk;
  575.     gIdlePhase := idleEnd;
  576.     gInBackground := FALSE;                             { When we start an app, it's in foreground }
  577.     gLastDeskAcc := gLastUpTime;
  578.  
  579.     gWResSignature := kNoIdentifier;
  580.     gWResType := '';
  581.  
  582.     { Create a work port for our convenience }
  583.     IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  584.         gWorkPort := NewCWindow(@gFakeWindow, gZeroRect, '', FALSE, documentProc, NIL, FALSE, 0)
  585.     ELSE
  586.         gWorkPort := NewWindow(@gFakeWindow, gZeroRect, '', FALSE, documentProc, NIL, FALSE, 0);
  587.  
  588.     gNextSpaceMsg := gLastUpTime;
  589.     gLowSpaceInterval := kLowSpaceInterval;
  590.  
  591.     {$IFC qDebug}
  592.     gBusyTempRgn := FALSE;
  593.     gUsedBy := '';
  594.     {$ENDC}
  595.  
  596.     gNoChanges := NIL;                                    { Left in for compatibility (2.0) }
  597.     gStdHysteresis := Point($00040004);                 { ??? any better choice ??? }
  598.  
  599.     SetPt(gZeroPt, 0, 0);
  600.     SetRect(gZeroRect, 0, 0, 0, 0);
  601.     SetVPt(gZeroVPt, 0, 0);
  602.     SetVRect(gZeroVRect, 0, 0, 0, 0);
  603.  
  604.     WITH GetGrayRgn^^.rgnBBox DO
  605.         BEGIN
  606.         SetRect(gStdWMoveBounds, left + 4, top + 4, right - 4, bottom - 4);
  607.  
  608.         { arbitrary minimum size; maximum size is grayRgn size minus half the title bar }
  609.         SetRect(gStdWSizeRect, 80, 80, right, bottom - 8 { half a title bar } );
  610.  
  611.         SetRect(gStdWScreenRect, left + 16, top + 16, right - 16, bottom - 16);
  612.         END;
  613.  
  614.     gOrthogonal[v] := h;
  615.     gOrthogonal[h] := v;
  616.  
  617.     gPrinting := FALSE;
  618.     gCurrPrintHandler := NIL;
  619.     gDrawingPictScrap := FALSE;
  620.     gDrawingPictScrapView := NIL;
  621.  
  622.     gFinderPrinting := FALSE;
  623.     gCouldPrint := FALSE;
  624.  
  625.     CountAppFiles(message, gFileCount);
  626.     gFinderPrinting := (message = appPrint);
  627.  
  628.     gHeadCohandler := NIL;
  629.     gEventLevel := 1;                                    { Prevents UnloadAllSegs from getting called
  630.                                                          if a modal dialogs is used befure starting
  631.                                                          the main event loop }
  632.  
  633.     New(gNullPrintHandler);
  634.     FailNil(gNullPrintHandler);
  635.     gNullPrintHandler.IPrintHandler(NIL);
  636.  
  637.     gPrintHandler := gNullPrintHandler;
  638.  
  639.     gFreeWindowList := NewList;
  640.  
  641.     {$IFC qDebug}
  642.     gFreeWindowList.SetEltType('TWindow');
  643.     {$ENDC}
  644.  
  645.     gChooserOK := TRUE;
  646.  
  647.     gClipWindow := NIL;
  648.  
  649.     gGotClipType := FALSE;
  650.  
  651.     gClipView := NIL;
  652.     gClipUndoView := NIL;
  653.  
  654.     gNumUntitled := 1;                                    { call the first document Untitled-1 }
  655.  
  656.     gUndoState := kShowUndo;
  657.     gUndoCmd := cNoCommand;
  658.     gErrorParm3 := '';
  659.     gFocusedView := NIL;
  660.     gStdStaggerCount := 0;
  661.  
  662.     gMBarDisplayed := kMBarDisplayed;
  663.     gMBarNotDisplayed := kMBarNotDisplayed;
  664.     gMBarHierarchical := kMBarHierarchical;
  665.  
  666.     { Compute the system font size, to be stuffed into gSystemStyle… }
  667.  
  668.     IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  669.         fontSize := GetDefFontSize
  670.     ELSE IF qNeedsROM128K | gConfiguration.hasROM128K THEN
  671.         fontSize := IntegerPtr(kLMSysFontSize)^
  672.     ELSE
  673.         fontSize := 12;                                 { Guess }
  674.     SetTextStyle(gSystemStyle, systemFont, [], fontSize, gRGBBlack);
  675.  
  676.     SetTextStyle(gApplicationStyle, applFont, [], 0, gRGBBlack);
  677.  
  678.     gOldChooserFlag := SetChooserAlert(FALSE);
  679.  
  680.     gSignatureCount := 0;
  681.  
  682.     IF qTemplateViews THEN
  683.         BEGIN
  684.         { =============================================== }
  685.         { Suppress Linker dead stripping of these classes }
  686.  
  687.         IF gDeadStripSuppression THEN
  688.             BEGIN
  689.             IF Member(TObject(NIL), TView) THEN;
  690.             IF Member(TObject(NIL), TWindow) THEN;
  691.             IF Member(TObject(NIL), TScrollBar) THEN;
  692.             IF Member(TObject(NIL), TSScrollBar) THEN;
  693.             IF Member(TObject(NIL), TScroller) THEN;
  694.             IF Member(TObject(NIL), TDeskScrapView) THEN;
  695.  
  696.             IF Member(TObject(NIL), TDocument) THEN;
  697.             IF Member(TObject(NIL), TNoChangesCommand) THEN;
  698.             IF Member(TObject(NIL), TList) THEN;
  699.             END;
  700.         { =============================================== }
  701.  
  702.         RegisterStdType('TView', kStdView);
  703.         RegisterStdType('TView', kStdDefaultView);
  704.         RegisterStdType('TWindow', kStdWindow);
  705.         RegisterStdType('TSScrollBar', kStdSScrollBar);
  706.         RegisterStdType('TScroller', kStdScroller);
  707.  
  708.         RegisterStdType('TDocument', kStdDocument);
  709.         RegisterStdType('TNoChangesCommand', kStdTracker);
  710.         RegisterStdType('TList', kStdList);
  711.         END;
  712.  
  713.     {$IFC qDebug}
  714.     gTraceSetupMenus := FALSE;
  715.     gTraceIdle := FALSE;
  716.     InitUDebug(NIL, NIL, @EntDebugger, @InspectObject,
  717.                @LookupSymbol);
  718.  
  719.     IF TrcEnable(TRUE) THEN;                            { Discard Result }
  720.     {$ENDC}
  721.  
  722.     InitUMenuSetup;
  723.  
  724.     {$IFC qDebug}
  725.     IF cUndo - cEditBase <> kSysUndo THEN
  726.         WriteLn('Invalid UNDO command number');
  727.     IF cCut - cEditBase <> kSysCut THEN
  728.         WriteLn('Invalid CUT command number');
  729.     IF cCopy - cEditBase <> kSysCopy THEN
  730.         WriteLn('Invalid COPY command number');
  731.     IF cPaste - cEditBase <> kSysPaste THEN
  732.         WriteLn('Invalid PASTE command number');
  733.     IF cClear - cEditBase <> kSysClear THEN
  734.         WriteLn('Invalid CLEAR command number');
  735.     {$ENDC}
  736.  
  737.     {$IFC qDebug}
  738.     GetKeys(gDebugKeyMap);
  739.     IF gDebugKeyMap[55] & gDebugKeyMap[56] & gDebugKeyMap[58] THEN { cmd-shift-option }
  740.         ProgramBreak('At start of application');
  741.     {$ENDC}
  742.  
  743.     END;
  744.  
  745. {--------------------------------------------------------------------------------------------------}
  746. {$S MANonRes}
  747.  
  748. FUNCTION GetWindowVariant(theWindow: WindowPtr): integer;
  749. { given a windowPtr, this routine returns its variant }
  750.  
  751.     BEGIN
  752.     IF TrapExists(_GetWVariant) THEN
  753.         GetWindowVariant := GetWVariant(theWindow)
  754.     ELSE
  755.         GetWindowVariant := BAND($0F, BSR(LONGINT(WindowPeek(theWindow)^.windowDefProc), 24));
  756.     END;
  757.  
  758. {--------------------------------------------------------------------------------------------------}
  759. {$S MARes}
  760.  
  761. PROCEDURE InstallIfPrintHandler(aPrintHandler: TPrintHandler; aView: TView);
  762.  
  763.     VAR
  764.         aNewPrintHandler: TPrintHandler;
  765.  
  766.     BEGIN
  767.     IF (aPrintHandler <> gNullPrintHandler) & (gPrintHandler <> gNullPrintHandler) &
  768.        (aPrintHandler <> NIL) & (aView <> NIL) THEN
  769.         BEGIN
  770.         aNewPrintHandler := TPrintHandler(aPrintHandler.clone);
  771.         IF aPrintHandler <> NIL THEN
  772.             BEGIN
  773.             IF aView.fDocument <> NIL THEN
  774.                 BEGIN
  775.                 aView.fDocument.fDocPrintHandler := aNewPrintHandler;
  776.                 aNewPrintHandler.fDocument := aView.fDocument;
  777.                 END;
  778.             aNewPrintHandler.fView := aView;
  779.             aNewPrintHandler.SetDefaultPrintInfo;
  780.             aView.AttachPrintHandler(aNewPrintHandler);
  781.             END;
  782.         END;
  783.     END;
  784.  
  785. {--------------------------------------------------------------------------------------------------}
  786. {$S MAError}
  787.  
  788. FUNCTION LookupErrString(value: INTEGER;
  789.                          resourceID: INTEGER;
  790.                          VAR str: Str255): BOOLEAN;
  791.  
  792.     FUNCTION SearchTable(value: INTEGER;
  793.                          resourceID: INTEGER;
  794.                          VAR str: Str255): BOOLEAN;
  795.  
  796.         LABEL 1;
  797.  
  798.         TYPE
  799.             ErrRecordHandle     = ^ErrRecord;
  800.             ErrRecord            = RECORD
  801.                 lowErr, highErr, index: INTEGER;
  802.                 END;
  803.  
  804.         VAR
  805.             table:                Handle;
  806.             pEntry:             ErrRecordHandle;
  807.             tableOffset:        LongInt;
  808.             lenTab:             INTEGER;
  809.             strID:                INTEGER;
  810.             i:                    INTEGER;
  811.  
  812.         BEGIN
  813.         SearchTable := FALSE;
  814.         str := '';
  815.  
  816.         table := GetResource('errs', resourceID);
  817.         IF table <> NIL THEN
  818.             BEGIN
  819.             lenTab := GetHandleSize(Handle(table)) DIV SIZEOF(ErrRecord);
  820.  
  821.             strID := 0;
  822.             tableOffset := 0;
  823.  
  824.             FOR i := 1 TO lenTab DO
  825.                 BEGIN
  826.                 pEntry := ErrRecordHandle(Ord4(table^) + tableOffset);
  827.  
  828.                 WITH pEntry^ DO
  829.                     BEGIN
  830.                     IF lowErr = 0 THEN
  831.                         strID := index
  832.                     ELSE IF (lowErr <= value) & (value <= highErr) THEN
  833.                         BEGIN
  834.                         IF index > 0 THEN
  835.                             GetIndString(str, strID, index);
  836.                         SearchTable := TRUE;
  837.                         GOTO 1;                         { exit the loop }
  838.                         END;
  839.                     END;
  840.  
  841.                 tableOffset := tableOffset + SIZEOF(ErrRecord);
  842.                 END;
  843.         1:
  844.             END;
  845.         END;
  846.  
  847.     BEGIN
  848.     IF SearchTable(value, errAppTable + resourceID, str) THEN
  849.         LookupErrString := TRUE
  850.     ELSE
  851.         LookupErrString := SearchTable(value, resourceID, str);
  852.     END;
  853.  
  854. {--------------------------------------------------------------------------------------------------}
  855. {$S MADebug}
  856.  
  857. FUNCTION LookupSymbol(VAR sym: Str255): LongInt;
  858.  
  859.     BEGIN
  860.     IF gInitialized THEN
  861.         LookupSymbol := gTarget.LookupSymbol(sym)
  862.     ELSE
  863.         LookupSymbol := - 1;
  864.     END;
  865.  
  866. {--------------------------------------------------------------------------------------------------}
  867. {$S MAGlobalsRes}                                        { Don't require a segment load for this }
  868.  
  869. VAR
  870.     bufferString:        String8;                        { If any script has a character with more
  871.                                                          than 8 bytes then the creatures that speak
  872.                                                          that language have too many fingers! }
  873.  
  874. FUNCTION MacAppAlertFilter(theDialog: DialogPtr;
  875.                            VAR theEvent: EventRecord;
  876.                            VAR itemHit: INTEGER): BOOLEAN;
  877.  
  878. { MacAppAlertFilter is a default filterProc used by MacAppAlert if the filterProc passed in is NIL.
  879.   It maps key strokes to the first character of button item titles.  It also hands off activate
  880.   and update processing to gApplication if we're not being called from an error condition or
  881.   while nested. }
  882.  
  883.     LABEL 1000;
  884.  
  885.     VAR
  886.         theChar:            CHAR;
  887.         itemType:            INTEGER;
  888.         item:                Handle;
  889.         box:                Rect;
  890.         byteType:            INTEGER;
  891.         fi:                 FailInfo;
  892.         oldInFilterState:    BOOLEAN;
  893.         anEvent:            EventRecord;
  894.  
  895.     PROCEDURE HdlFilter(error: INTEGER;
  896.                         message: LongInt);
  897.  
  898.         BEGIN
  899.         GOTO 1000;
  900.         END;
  901.  
  902.     FUNCTION GetButtonTitle(itemNo: INTEGER): String8;
  903.     { Retrieve the title of the button control.
  904.       If itemNo isn't a button, then return ''. }
  905.  
  906.         VAR
  907.             title:                Str255;
  908.  
  909.         BEGIN
  910.         GetDItem(theDialog, itemNo, itemType, item, box);
  911.         IF itemType <> (ctrlItem + btnCtrl) THEN
  912.             title := ''
  913.         ELSE
  914.             GetCTitle(ControlHandle(item), title);
  915.         GetButtonTitle := title;
  916.         END;
  917.  
  918.     PROCEDURE DoKeyDown(itemNo: INTEGER);
  919.     { Handle a keypress that has been mapped to one of the button controls. }
  920.  
  921.         VAR
  922.             finalTicks:         LongInt;
  923.  
  924.         BEGIN
  925.         MacAppAlertFilter := TRUE;
  926.         itemHit := itemNo;
  927.         GetDItem(theDialog, itemNo, itemType, item, box);
  928.         IF itemType = (ctrlItem + btnCtrl) THEN
  929.             BEGIN                                        { this code gives visual feedback }
  930.             HiliteControl(ControlHandle(item), inButton); { hilite the button }
  931.             Delay(8, finalTicks);                        { delay for 8 ticks }
  932.             HiliteControl(ControlHandle(item), 0);        { stop hiliting the button }
  933.             END;
  934.         END;
  935.  
  936.     FUNCTION TestAString(aString: String8): BOOLEAN;
  937.     { in the case of Script Manager systems, use CharByte to determine character boundaries
  938.       and compare the input to the button titles }
  939.  
  940.         VAR
  941.             textOffset:         INTEGER;
  942.             done, areEqual:     BOOLEAN;
  943.  
  944.         BEGIN
  945.         textOffset := 0;
  946.         done := FALSE;
  947.         REPEAT
  948.             IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  949.                 byteType := CharByte(@aString[1], textOffset) { textOffset is zero-based }
  950.             ELSE
  951.                 byteType := smSingleByte;
  952.  
  953.             textOffset := textOffset + 1;
  954.             areEqual := aString[textOffset] = bufferString[textOffset];
  955.             CASE byteType OF
  956.                 smSingleByte:
  957.                     BEGIN                                { special case single byte characters to
  958.                                                          allow lower case characters to map to
  959.                                                          upper case characters }
  960.                     areEqual := LowerChar(aString[1]) = LowerChar(bufferString[1]);
  961.                     done := TRUE;
  962.                     END;
  963.                 smFirstByte:
  964.                     done := NOT areEqual;                { we're done if they don't match }
  965.                 smLastByte:
  966.                     done := TRUE;
  967.                 smMiddleByte:
  968.                     done := NOT areEqual;                { we're done if they don't match }
  969.             END;
  970.         UNTIL done;
  971.         TestAString := areEqual;
  972.         END;
  973.  
  974.     PROCEDURE DoAddByte(theChar: CHAR);
  975.     { adds the incoming byte to the bufferString of typed characters }
  976.  
  977.         VAR
  978.             buffIndex:            INTEGER;
  979.  
  980.         BEGIN
  981.         buffIndex := ORD(bufferString[0]) + 1;            { increment count }
  982.         bufferString[buffIndex] := theChar;             { assign new character }
  983.         bufferString[0] := CHR(buffIndex);                { assign length byte }
  984.         END;
  985.  
  986.     PROCEDURE DoLastByte(theChar: CHAR);
  987.     { adds the last incoming byte to the bufferString of typed characters
  988.     and compares the bufferString to the first character of each button title
  989.     1st button in alert (by convention = "OK").  2nd button in alert (by convention =
  990.     "Cancel").    3rd button in alert (by convention = "No") }
  991.  
  992.         BEGIN
  993.         DoAddByte(theChar);
  994.         IF TestAString(GetButtonTitle(ok)) THEN
  995.             DoKeyDown(ok)
  996.         ELSE IF TestAString(GetButtonTitle(cancel)) THEN
  997.             DoKeyDown(cancel)
  998.         ELSE IF TestAString(GetButtonTitle(kNoButton)) THEN
  999.             DoKeyDown(kNoButton);
  1000.         bufferString := '';                             { initialize bufferString }
  1001.         END;
  1002.  
  1003.     BEGIN                                                { MacAppAlertFilter }
  1004.     MacAppAlertFilter := FALSE;
  1005.     oldInFilterState := gInFilter;
  1006.     gInFilter := TRUE;
  1007.     CatchFailures(fi, HdlFilter);
  1008.  
  1009.     { Wouldn't want MacApp to get lied to about where the focus _Actually_ is }
  1010.     IF (gApplication <> NIL) & NOT gInhibitNestedHandling & NOT oldInFilterState THEN
  1011.         gApplication.InvalidateFocus;
  1012.  
  1013.     CASE theEvent.what OF
  1014.         activateEvt:                                    { this is the first event the alert gets, so
  1015.                                                          let's determine our VARs }
  1016.             BEGIN
  1017.             IF DialogPtr(theEvent.message) = theDialog THEN
  1018.                 BEGIN
  1019.                 bufferString := '';                     { initialize bufferString }
  1020.                 END
  1021.             ELSE IF (gApplication <> NIL) & NOT gInhibitNestedHandling & NOT oldInFilterState THEN
  1022.                 gApplication.HandleEvent(theEvent);
  1023.             END;
  1024.  
  1025.         updateEvt:                                        { this is the first event the alert gets, so
  1026.                                                          let's determine our VARs }
  1027.             BEGIN
  1028.             IF DialogPtr(theEvent.message) <> theDialog THEN
  1029.                 IF (gApplication <> NIL) & NOT gInhibitNestedHandling & NOT oldInFilterState THEN
  1030.                     gApplication.HandleEvent(theEvent);
  1031.             END;
  1032.         keyDown:                                        { let's determine if the key pressed
  1033.                                                          corresponds to our button titles }
  1034.             BEGIN
  1035.             theChar := CHR(BAND(theEvent.message, charCodeMask));
  1036.             IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  1037.                 byteType := CharByte(@theChar, 0)
  1038.             ELSE
  1039.                 byteType := smLastByte;                 { punt...treat each byte as the last
  1040.                                                          character }
  1041.             CASE byteType OF
  1042.                 smSingleByte:
  1043.                     IF (theChar = chEnter) | (theChar = chReturn) THEN
  1044.                         DoKeyDown(ok)
  1045.                     ELSE IF (theChar = chEscape) | ((theChar = '.') & (BAND(theEvent.modifiers,
  1046.                             cmdKey) <> 0)) THEN
  1047.                         DoKeyDown(cancel)
  1048.                     ELSE
  1049.                         DoLastByte(theChar);
  1050.                 smFirstByte:
  1051.                     DoAddByte(theChar);
  1052.                 smLastByte:
  1053.                     DoLastByte(theChar);
  1054.                 smMiddleByte:
  1055.                     DoAddByte(theChar);
  1056.             END;                                        { CASE }
  1057.             END;
  1058.     END;
  1059.  
  1060.     { Idle but only if _REALLY_ necessary }
  1061.     IF (gApplication <> NIL) & NOT gInhibitNestedHandling & NOT oldInFilterState &
  1062.        NOT EventAvail(everyEvent, anEvent) THEN
  1063.         gApplication.Idle(gIdlePhase);
  1064.  
  1065.     Success(fi);
  1066. 1000:
  1067.     gInFilter := oldInFilterState;
  1068.     END;                                                { MacAppAlertFilter }
  1069.  
  1070. {--------------------------------------------------------------------------------------------------}
  1071. {$Push}
  1072. {$MC68020-}                                             { Need to be able to alert user if this
  1073.                                                          isn't a 68020 machine, alert filter won't
  1074.                                                          be installed until after that, though. }
  1075. {$S MAGlobalsRes}                                        { Don't require a segment load for this }
  1076.  
  1077. FUNCTION MacAppAlert(alertID: INTEGER;
  1078.                      filterProc: ProcPtr): INTEGER;
  1079.  
  1080.     VAR
  1081.         alrtTemplate:        AlertTHndl;
  1082.     
  1083.     FUNCTION CanAlert:Boolean;                            { ensures that the Alert won't fail }
  1084.  
  1085.         BEGIN
  1086.         CouldAlert(alertID);
  1087.         CanAlert := (ResError = NoErr) & (MemError = NoErr);
  1088.         FreeAlert(alertID);
  1089.         END;
  1090.  
  1091.     BEGIN
  1092.     {$IFC qDebug}
  1093.     gRsrcCheck := 0;                                    { force immediate check. }
  1094.     {$ENDC}
  1095.  
  1096.     SetCursor(arrow);
  1097.     alrtTemplate := AlertTHndl(GetResource('ALRT', alertID));
  1098.     IF alrtTemplate <> NIL THEN
  1099.         BEGIN
  1100.         IF GetResource('DITL', alertID) = NIL THEN        { preflight the DITL }
  1101.             BEGIN                                        { DITL is missing or not enough memory }
  1102.             {$IFC qDebug}
  1103.             ProgramBreak(ConcatNumber('Unable to find or load ‘DITL’ resource ', alertID));
  1104.             {$ENDC}
  1105.             SysBeep(2);                                 { At least give some indication }
  1106.             MacAppAlert := 1;                            { Arbitrary result }
  1107.             END
  1108.         ELSE
  1109.             BEGIN
  1110.             IF NOT CanAlert THEN
  1111.                 BEGIN                                    { no can do }
  1112.                 {$IFC qDebug}
  1113.                 ProgramBreak(ConcatNumber('Unable to display alert ', alertID));
  1114.                 {$ENDC}
  1115.                 SysBeep(2);                             { At least give some indication }
  1116.                 MacAppAlert := 1;                        { Arbitrary result }
  1117.                 END
  1118.             ELSE
  1119.                 BEGIN
  1120.                 LockHandleHigh(Handle(alrtTemplate));
  1121.                 CenterRectOnScreen(alrtTemplate^^.boundsRect, TRUE, TRUE, TRUE);
  1122.                 PullApplicationToFront;
  1123.                 IF (filterProc = NIL) THEN
  1124.                     MacAppAlert := Alert(alertID, gMacAppAlertFilter)
  1125.                 ELSE
  1126.                     MacAppAlert := Alert(alertID, filterProc);
  1127.                 END
  1128.             END
  1129.         END
  1130.     ELSE
  1131.         BEGIN
  1132.         {$IFC qDebug}
  1133.         ProgramBreak(ConcatNumber('Unable to find or load ‘ALRT’ resource ', alertID));
  1134.         {$ENDC}
  1135.         SysBeep(2);                                     { At least give some indication }
  1136.         MacAppAlert := 1;                                { Arbitrary result }
  1137.         END;
  1138.  
  1139.     IF gApplication <> NIL THEN
  1140.         gApplication.InvalidateCursorRgn;
  1141.  
  1142.     InvalidateMenus;
  1143.     END;
  1144. {$Pop}
  1145.  
  1146. {--------------------------------------------------------------------------------------------------}
  1147. {$S MAGlobalsRes}
  1148.  
  1149. FUNCTION MakeNewRgn: RgnHandle;
  1150.  
  1151.     VAR
  1152.         aRgn:                RgnHandle;
  1153.  
  1154.     BEGIN
  1155.     aRgn := NewRgn;
  1156.     FailNil(aRgn);
  1157.     MakeNewRgn := aRgn;
  1158.     END;
  1159.  
  1160. {--------------------------------------------------------------------------------------------------}
  1161. {$S MAOpen}
  1162.  
  1163. FUNCTION NewPaletteWindow(itsRsrcID: INTEGER;
  1164.                           wantHScrollBar, wantVScrollBar: BOOLEAN;
  1165.                           itsDocument: TDocument;
  1166.                           itsMainView: TView;
  1167.                           itsPaletteView: TView;
  1168.                           sizePalette: INTEGER;
  1169.                           whichWay: VHSelect): TWindow;
  1170.  
  1171.     VAR
  1172.         aWindow:            TWindow;
  1173.         aScroller:            TScroller;
  1174.         fi:                 FailInfo;
  1175.         itsSize:            VPoint;
  1176.         itsLocation:        VPoint;
  1177.         wSize:                Point;
  1178.         sBarOffsets:        VRect;
  1179.  
  1180.     PROCEDURE HdlNPWindow(error: INTEGER;
  1181.                           message: LongInt);
  1182.  
  1183.         BEGIN
  1184.         FreeIfObject(aWindow);
  1185.         aWindow := NIL;
  1186.         END;
  1187.  
  1188.     BEGIN
  1189.     aWindow := NewTWindow(itsRsrcID, itsDocument);
  1190.  
  1191.     WITH aWindow.fResizeLimits.topLeft DO
  1192.         vh[whichWay] := vh[whichWay] + sizePalette;
  1193.  
  1194.     CatchFailures(fi, HdlNPWindow);
  1195.  
  1196.     aWindow.AddSubView(itsPaletteView);
  1197.  
  1198.     itsLocation := gZeroVPt;
  1199.     itsLocation.vh[whichWay] := sizePalette;
  1200.     IF wantHScrollBar | wantVScrollBar THEN
  1201.         BEGIN
  1202.         sBarOffsets := gZeroVRect;
  1203.         itsSize := aWindow.fSize;
  1204.         IF wantHScrollBar THEN
  1205.             BEGIN
  1206.             itsSize.v := itsSize.v - kSBarSizeMinus1;
  1207.             IF NOT wantVScrollBar THEN
  1208.                 sBarOffsets.right := - kSBarSizeMinus1;
  1209.             END;
  1210.         IF wantVScrollBar THEN
  1211.             BEGIN
  1212.             itsSize.h := itsSize.h - kSBarSizeMinus1;
  1213.             IF NOT wantHScrollBar THEN
  1214.                 sBarOffsets.bottom := - kSBarSizeMinus1;
  1215.             END;
  1216.         itsSize.vh[whichWay] := itsSize.vh[whichWay] - sizePalette;
  1217.         New(aScroller);
  1218.         FailNil(aScroller);
  1219.         aScroller.IScroller(aWindow, itsLocation, itsSize, sizeRelSuperView, sizeRelSuperView, 0, 0,
  1220.                             wantHScrollBar, wantVScrollBar);
  1221.         aScroller.fSBarOffsets := sBarOffsets;
  1222.         aScroller.AddSubView(itsMainView);
  1223.         END
  1224.     ELSE
  1225.         aWindow.AddSubView(itsMainView);
  1226.  
  1227.     aWindow.SetTarget(itsMainView);
  1228.  
  1229.     { make frames be the right size }
  1230.     WITH aWindow.fWMgrWindow^.portRect DO
  1231.         BEGIN
  1232.         wSize := botRight;
  1233.         {$Push} {$H-}
  1234.         SubPt(topLeft, wSize);
  1235.         {$Pop}
  1236.         END;
  1237.     aWindow.Resize(wSize.h, wSize.v, kDontInvalidate);
  1238.  
  1239.     NewPaletteWindow := aWindow;
  1240.  
  1241.     Success(fi);
  1242.     END;
  1243.  
  1244. {--------------------------------------------------------------------------------------------------}
  1245. {$S MAOpen}
  1246.  
  1247. FUNCTION NewSimpleWindow(itsRsrcID: INTEGER;
  1248.                          wantHScrollBar, wantVScrollBar: BOOLEAN;
  1249.                          itsDocument: TDocument;
  1250.                          itsView: TView): TWindow;
  1251.  
  1252.     VAR
  1253.         aWindow:            TWindow;
  1254.         aScroller:            TScroller;
  1255.         fi:                 FailInfo;
  1256.         itsSize:            VPoint;
  1257.         wSize:                Point;
  1258.         sBarOffsets:        VRect;
  1259.  
  1260.     PROCEDURE HdlNSWindow(error: INTEGER;
  1261.                           message: LongInt);
  1262.  
  1263.         BEGIN
  1264.         FreeIfObject(aWindow);
  1265.         aWindow := NIL;
  1266.         END;
  1267.  
  1268.     BEGIN
  1269.     aWindow := NewTWindow(itsRsrcID, itsDocument);
  1270.  
  1271.     aScroller := NIL;
  1272.  
  1273.     CatchFailures(fi, HdlNSWindow);
  1274.  
  1275.     IF wantHScrollBar | wantVScrollBar THEN
  1276.         BEGIN
  1277.         sBarOffsets := gZeroVRect;
  1278.         itsSize := aWindow.fSize;
  1279.         IF wantHScrollBar THEN
  1280.             BEGIN
  1281.             itsSize.v := itsSize.v - kSBarSizeMinus1;
  1282.             IF NOT wantVScrollBar THEN
  1283.                 sBarOffsets.right := - kSBarSizeMinus1;
  1284.             END;
  1285.         IF wantVScrollBar THEN
  1286.             BEGIN
  1287.             itsSize.h := itsSize.h - kSBarSizeMinus1;
  1288.             IF NOT wantHScrollBar THEN
  1289.                 sBarOffsets.bottom := - kSBarSizeMinus1;
  1290.             END;
  1291.         New(aScroller);
  1292.         FailNil(aScroller);
  1293.         aScroller.IScroller(aWindow, gZeroVPt, itsSize, sizeRelSuperView, sizeRelSuperView, 0, 0,
  1294.                             wantHScrollBar, wantVScrollBar);
  1295.         aScroller.fSBarOffsets := sBarOffsets;
  1296.         IF itsView <> NIL THEN
  1297.             aScroller.AddSubView(itsView);
  1298.         END
  1299.     ELSE IF itsView <> NIL THEN
  1300.         aWindow.AddSubView(itsView);
  1301.  
  1302.     aWindow.SetTarget(itsView);
  1303.  
  1304.     { make sure window and subviews are the right size }
  1305.     WITH aWindow.fWMgrWindow^.portRect DO
  1306.         BEGIN
  1307.         wSize := botRight;
  1308.         {$Push} {$H-}
  1309.         SubPt(topLeft, wSize);
  1310.         {$Pop}
  1311.         END;
  1312.     aWindow.Resize(wSize.h, wSize.v, kDontInvalidate);
  1313.  
  1314.     NewSimpleWindow := aWindow;
  1315.  
  1316.     Success(fi);
  1317.     END;
  1318.  
  1319. {--------------------------------------------------------------------------------------------------}
  1320. {$S MAOpen}
  1321.  
  1322. FUNCTION NewStdObject(signature: IDType): TObject;
  1323.  
  1324.     VAR
  1325.         i:                    INTEGER;
  1326.         obj:                TObject;
  1327.  
  1328.     BEGIN
  1329.     FOR i := 1 TO gSignatureCount DO
  1330.         IF LongInt(gSignatures[i]) = LongInt(signature) THEN
  1331.             BEGIN
  1332.             NewStdObject := NewObjectByClassId(gSignatureIds[i]);
  1333.             EXIT(NewStdObject);
  1334.             END;
  1335.  
  1336.     {$IFC qDebug}
  1337.     WriteLn('signature=‘', signature, '’');
  1338.     ProgramBreak('Unable to find class for the given signature');
  1339.     {$ENDC}
  1340.     NewStdObject := NIL;
  1341.     END;
  1342.  
  1343. {--------------------------------------------------------------------------------------------------}
  1344. {$S MAOpen}
  1345.  
  1346. FUNCTION NewTWindow(itsRsrcID: INTEGER;
  1347.                     itsDocument: TDocument): TWindow;
  1348.  
  1349.     VAR
  1350.         aWMgrWindow:        WindowPtr;
  1351.         aWindow:            TWindow;
  1352.         canResize:            BOOLEAN;
  1353.         canClose:            BOOLEAN;
  1354.         fi:                 FailInfo;
  1355.  
  1356.     PROCEDURE HdlNewWObj(error: INTEGER;
  1357.                          message: LongInt);
  1358.  
  1359.         BEGIN
  1360.         { the wmgrWindow is known to exist }
  1361.   { Since aWindow didn't get created, the wmgrWindow won't be
  1362.    freed unless we do it here. }
  1363.  
  1364.         aWMgrWindow := FreeIfWMgrWindow(aWMgrWindow, TRUE);
  1365.  
  1366.         END;
  1367.  
  1368.     BEGIN
  1369.     aWMgrWindow := NIL;
  1370.     aWMgrWindow := gApplication.GetRsrcWindow(NIL, itsRsrcID, canResize, canClose);
  1371.     { GetRsrcWindow signals Failure }
  1372.  
  1373.     CatchFailures(fi, HdlNewWObj);
  1374.  
  1375.     aWindow := NIL;
  1376.  
  1377.     New(aWindow);
  1378.     FailNil(aWindow);
  1379.     Success(fi);
  1380.  
  1381.     aWindow.IWindow(itsDocument, aWMgrWindow, canResize, canClose, TRUE); { TRUE means can dispose
  1382.                                                                            wmgr window }
  1383.  
  1384.     NewTWindow := aWindow;
  1385.  
  1386.     END;
  1387.  
  1388. {--------------------------------------------------------------------------------------------------}
  1389. {$S MAOpen}
  1390.  
  1391. FUNCTION NewTemplateWindow(viewRsrcID: INTEGER;
  1392.                            itsDocument: TDocument): TWindow;
  1393.  
  1394.     VAR
  1395.         theWindow:            TWindow;
  1396.         theTarget:            TView;
  1397.         aView:                TView;
  1398.  
  1399.     BEGIN
  1400.     theWindow := NIL;
  1401.  
  1402.     aView := gTarget.DoCreateViews(itsDocument, NIL, viewRsrcID, gZeroVPt);
  1403.     IF aView <> NIL THEN
  1404.         BEGIN
  1405.         IF qDebug & NOT MEMBER(aView, TWindow) THEN
  1406.             ProgramBreak('In NewTemplateWindow: Root view is not a window');
  1407.  
  1408.         theWindow := TWindow(aView);
  1409.  
  1410.         IF theWindow.fWMgrWindow <> NIL THEN
  1411.             WITH theWindow.fWMgrWindow^.portRect DO
  1412.                 theWindow.Resize(right - left, bottom - top, kDontInvalidate);
  1413.         IF theWindow.fTargetID <> kNoIdentifier THEN
  1414.             BEGIN
  1415.             theTarget := theWindow.FindSubView(theWindow.fTargetID);
  1416.             IF theTarget <> NIL THEN
  1417.                 theWindow.SetTarget(theTarget)
  1418.             ELSE IF qDebug THEN
  1419.                 ProgramBreak('The window has no view whose id is fTargetId.');
  1420.             END;
  1421.         END;
  1422.     NewTemplateWindow := theWindow;
  1423.     END;
  1424.  
  1425. {--------------------------------------------------------------------------------------------------}
  1426. {$S MAGlobalsRes}
  1427.  
  1428. FUNCTION NewViewRsrc(VAR p: UNIV Ptr): ViewRsrcHndl;
  1429.  
  1430.     VAR
  1431.         aHandle:            ViewRsrcHndl;
  1432.  
  1433.     BEGIN
  1434.     aHandle := ViewRsrcHndl(NewPermHandle(kViewRsrcExpandAmt));
  1435.     FailNil(aHandle);
  1436.     LockHandleHigh(Handle(aHandle));
  1437.     WITH aHandle^^ DO
  1438.         BEGIN
  1439.         numViews := 0;
  1440.         p := @theViews;
  1441.         END;
  1442.     NewViewRsrc := aHandle;
  1443.     END;
  1444.  
  1445. {--------------------------------------------------------------------------------------------------}
  1446. {$S MADebug}
  1447.  
  1448. PROCEDURE NotYetImplemented(where: Str255);
  1449.  
  1450.     BEGIN
  1451.     Failure(errNotImplemented, 0);
  1452.     END;
  1453.  
  1454. {--------------------------------------------------------------------------------------------------}
  1455. {$S MAOpen}
  1456.  
  1457. PROCEDURE OffsetPtr(VAR p: UNIV LongInt;
  1458.                     offset: LongInt);
  1459.  
  1460.     BEGIN
  1461.     p := p + offset;
  1462.     IF ODD(p) THEN
  1463.         p := p + 1;
  1464.     END;
  1465.  
  1466. {--------------------------------------------------------------------------------------------------}
  1467. {$S MAOpen}
  1468.  
  1469. PROCEDURE OffsetPtrWStr(VAR p: UNIV LongInt;
  1470.                         offset: LongInt);
  1471.  
  1472.     BEGIN
  1473.     OffsetPtr(p, offset - 255 + LENGTH(StringPtr(p + offset - 256)^));
  1474.     END;
  1475.  
  1476. {--------------------------------------------------------------------------------------------------}
  1477. {$S MAGlobalsRes}
  1478.  
  1479. FUNCTION ParseTitleTemplate(VAR itsTemplate: Str255;
  1480.                             VAR preDocname, constTitle: INTEGER): BOOLEAN;
  1481.  
  1482.     CONST
  1483.         kPreDocname         = '<<<';
  1484.         kPreSize            = 3;
  1485.         kPostDocname        = '>>>';
  1486.         kPostSize            = 3;
  1487.  
  1488.     VAR
  1489.         x:                    INTEGER;
  1490.  
  1491.     FUNCTION FindPos(pattern: Str255;
  1492.                      VAR source: Str255): INTEGER;
  1493.  
  1494.         VAR
  1495.             i, j:                INTEGER;
  1496.             position:            INTEGER;
  1497.  
  1498.         BEGIN
  1499.         IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  1500.             BEGIN
  1501.             i := 0;
  1502.             REPEAT
  1503.                 i := i + 1;
  1504.                 position := i;
  1505.                 FOR j := 1 TO LENGTH(pattern) DO
  1506.                     IF NOT ((source[i + j - 1] = pattern[j]) & (CharByte(@source, i + j) = 0)) THEN
  1507.                         BEGIN
  1508.                         position := 0;
  1509.                         LEAVE;
  1510.                         END;
  1511.             UNTIL (position > 0) | (i >= LENGTH(source) - LENGTH(pattern) + 1);
  1512.             END
  1513.         ELSE
  1514.             position := POS(pattern, source);
  1515.  
  1516.         FindPos := position;
  1517.         END;
  1518.  
  1519.     BEGIN
  1520.     IF itsTemplate = '' THEN
  1521.         BEGIN
  1522.         preDocname := 1;
  1523.         constTitle := 0;
  1524.         END
  1525.     ELSE
  1526.         BEGIN
  1527.         preDocname := FindPos(kPreDocname, itsTemplate);
  1528.         IF preDocname > 0 THEN
  1529.             BEGIN
  1530.             Delete(itsTemplate, preDocname, kPreSize);
  1531.  
  1532.             x := FindPos(kPostDocname, itsTemplate);
  1533.             IF x = 0 THEN
  1534.                 constTitle := preDocname - 1
  1535.             ELSE
  1536.                 BEGIN
  1537.                 Delete(itsTemplate, x, kPostSize);
  1538.                 constTitle := LENGTH(itsTemplate) - x + preDocname;
  1539.                 END;
  1540.             END;
  1541.         END;
  1542.  
  1543.     ParseTitleTemplate := preDocname > 0;
  1544.     END;
  1545.  
  1546. {--------------------------------------------------------------------------------------------------}
  1547. {$S MAGlobalsRes}
  1548.  
  1549. FUNCTION PtIsVisible(pt: Point): BOOLEAN;
  1550.  
  1551.     BEGIN
  1552.     IF gDrawingPictScrap THEN
  1553.         PtIsVisible := TRUE
  1554.     ELSE
  1555.         PtIsVisible := PtInRgn(pt, thePort^.visRgn) & PtInRgn(pt, thePort^.clipRgn);
  1556.     END;
  1557.  
  1558. {--------------------------------------------------------------------------------------------------}
  1559. {$S MAActivate}
  1560.  
  1561. FUNCTION PutDeskScrapData(aResType: ResType;
  1562.                           aDataHandle: Handle): OSErr;
  1563.  
  1564.     VAR
  1565.         err:                LongInt;
  1566.  
  1567.     BEGIN
  1568.     LockHandleHigh(aDataHandle);
  1569.     err := PutScrap(GetHandleSize(aDataHandle), aResType, aDataHandle^);
  1570.     HUnlock(aDataHandle);
  1571.     {$IFC qDebug}
  1572.     IF err <> noErr THEN
  1573.         WriteLn('Error from PutScrap is: ', err: 1);
  1574.     {$ENDC}
  1575.     PutDeskScrapData := err;
  1576.     END;
  1577.  
  1578. {--------------------------------------------------------------------------------------------------}
  1579. {$S MAGlobalsRes}
  1580.  
  1581. FUNCTION RectIsVisible(r: Rect): BOOLEAN;
  1582.  
  1583.     BEGIN
  1584.     IF gDrawingPictScrap THEN
  1585.         RectIsVisible := TRUE
  1586.     ELSE
  1587.         RectIsVisible := RectInRgn(r, thePort^.visRgn) & RectInRgn(r, thePort^.clipRgn);
  1588.     END;
  1589.  
  1590. {--------------------------------------------------------------------------------------------------}
  1591. {$S MAGlobalsRes}
  1592.  
  1593. PROCEDURE RegisterStdType(typeName: Str255;
  1594.                           signature: IDType);
  1595. { Register or re-register a type and a class }
  1596.  
  1597.     VAR
  1598.         i:                    INTEGER;
  1599.  
  1600.     BEGIN
  1601.     { try to find an existing signature to replace }
  1602.     FOR i := 1 TO gSignatureCount DO
  1603.         IF LongInt(gSignatures[i]) = LongInt(signature) THEN
  1604.             BEGIN
  1605.             gSignatureIds[i] := GetClassIDFromName(typeName);
  1606.             { If the name can't be found it was probably misspelled or dead-stripped }
  1607.             IF gSignatureIds[i] = kNilClass THEN
  1608.                 Failure(minErr, 0);                     {??? need to assign a message???}
  1609.             EXIT(RegisterStdType);
  1610.             END;
  1611.  
  1612.     { not found to replace… add a new one }
  1613.     gSignatureCount := gSignatureCount + 1;
  1614.     {$IFC qDebug}
  1615.     IF gSignatureCount >= kMaxSignatures THEN
  1616.         ProgramBreak('Maximum number of signatures exceeded.');
  1617.     {$ENDC}
  1618.     gSignatures[gSignatureCount] := signature;
  1619.     gSignatureIds[gSignatureCount] := GetClassIDFromName(typeName);
  1620.     END;
  1621.  
  1622. {--------------------------------------------------------------------------------------------------}
  1623. {$S MAGlobalsRes}
  1624.  
  1625. PROCEDURE SetFocus(theFocusRec: FocusRec);
  1626.  
  1627.     BEGIN
  1628.     WITH theFocusRec DO
  1629.         BEGIN
  1630.         SetPort(Port);
  1631.         SetOrigin(Org.h, Org.v);
  1632.         SetClip(Clip);
  1633.         gLongOffset := LongOffset;
  1634.         gFocusedView := FocusedView;
  1635.         gPrinting := printing;
  1636.         gDrawingPictScrap := drawingPictScrap;
  1637.         gDrawingPictScrapView := drawingPictScrapView;
  1638.         END;
  1639.     END;
  1640.  
  1641. {--------------------------------------------------------------------------------------------------}
  1642. {$S MAGlobalsRes}
  1643.  
  1644. PROCEDURE SetHLPenState(fromHL, toHL: HLState);
  1645.  
  1646.     VAR
  1647.         pPat:                ^pattern;
  1648.         mode:                INTEGER;
  1649.  
  1650.     BEGIN
  1651.     mode := patXOR;                                     { every transition except hlOn <-> hlDim
  1652.                                                          uses patXOR }
  1653.  
  1654.     IF fromHL = toHL THEN
  1655.         pPat := @white
  1656.  
  1657.     ELSE IF fromHL + toHL = hlOffOn THEN
  1658.         pPat := @black
  1659.  
  1660.     ELSE
  1661.         pPat := @gray;                                    { ??? make this pattern a parameter ??? }
  1662.  
  1663.     IF fromHL + toHL = hlDimOn THEN
  1664.         mode := NOTpatXOR;
  1665.  
  1666.     PenMode(mode);
  1667.     PenPat(pPat^);
  1668.     END;
  1669.  
  1670. {--------------------------------------------------------------------------------------------------}
  1671. {$Push}
  1672. {$MC68020-}                                             { Need to be able to alert user if this
  1673.                                                          isn't a 68020 machine }
  1674. {$S MAGlobalsRes}                                        { Don't require a segment load for this }
  1675.  
  1676. PROCEDURE StdAlert(alertID: INTEGER);
  1677.  
  1678.     VAR
  1679.         reply:                INTEGER;
  1680.  
  1681.     BEGIN
  1682.     reply := MacAppAlert(alertID, NIL);
  1683.     END;
  1684. {$Pop}
  1685.  
  1686. {--------------------------------------------------------------------------------------------------}
  1687. {$S MAGlobalsRes}
  1688.  
  1689. FUNCTION SubstituteInTitle(VAR title: Str255;
  1690.                            newStuff: Str255;
  1691.                            preDocname, constTitle: INTEGER): BOOLEAN;
  1692.  
  1693.     BEGIN
  1694.     IF preDocname > 0 THEN
  1695.         BEGIN
  1696.         IF constTitle = 0 THEN
  1697.             title := newStuff
  1698.         ELSE
  1699.             BEGIN
  1700.             Delete(title, preDocname, LENGTH(title) - constTitle);
  1701.             Insert(newStuff, title, preDocname);
  1702.             END;
  1703.         SubstituteInTitle := TRUE;
  1704.         END
  1705.     ELSE
  1706.         SubstituteInTitle := FALSE;
  1707.     END;
  1708.  
  1709. {--------------------------------------------------------------------------------------------------}
  1710. {$IFC qDebug}
  1711. {$S MADebug}
  1712. {$Push} {$IFC qTrace} {$D+} {$ENDC}
  1713.  
  1714. PROCEDURE UseTempRgn(byWhom: Str255);
  1715.  { Call this when you are about to use gTempRgn and qDebug is true. Used
  1716.   with DoneWithTempRgn will prevent you from trying to use gTempRgn
  1717.   from two places at the same time. }
  1718.  
  1719.     BEGIN
  1720.     IF gBusyTempRgn THEN
  1721.         BEGIN
  1722.         WriteLn('"', byWhom, '" is trying to lock gTempRgn,');
  1723.         WriteLn('but it is already locked by "', gUsedBy, '"');
  1724.         ProgramBreak('Error in UseTempRgn');
  1725.         END
  1726.     ELSE
  1727.         BEGIN
  1728.         gBusyTempRgn := TRUE;
  1729.         gUsedBy := byWhom;
  1730.         END;
  1731.     END;
  1732. {$Pop}
  1733. {$ENDC qDebug}
  1734.  
  1735. {--------------------------------------------------------------------------------------------------}
  1736. {$S MAGlobalsRes}
  1737.  
  1738. PROCEDURE VisibleRect(VAR r: Rect);
  1739.  
  1740.     BEGIN
  1741.     IF NOT gDrawingPictScrap THEN
  1742.         BEGIN
  1743.         {$IFC qDebug}
  1744.         UseTempRgn('VisibleRect');
  1745.         {$ENDC}
  1746.         RectRgn(gTempRgn, r);
  1747.         
  1748.         { Some print drivers don't set the visRgn correctly.
  1749.         ??? Shouldn't this really be accounted for in printhandler code }
  1750.         IF NOT gPrinting THEN
  1751.             SectRgn(gTempRgn, thePort^.visRgn, gTempRgn);
  1752.         SectRgn(gTempRgn, thePort^.clipRgn, gTempRgn);
  1753.         r := gTempRgn^^.rgnBBox;
  1754.         {$IFC qDebug}
  1755.         DoneWithTempRgn;
  1756.         {$ENDC}
  1757.         END;
  1758.     END;
  1759.  
  1760. {--------------------------------------------------------------------------------------------------}
  1761. {$IFC qDebug}
  1762. {$S MADebug}
  1763.  
  1764. PROCEDURE WriteFocus;
  1765.  
  1766.     BEGIN
  1767.     WrLblVPt('  gLongOffset', gLongOffset);
  1768.     WriteLn;
  1769.     WrLblRect('     portRect', thePort^.portRect);
  1770.     WriteLn;
  1771.     WrLblRect('       visRgn', thePort^.visRgn^^.rgnBBox);
  1772.     WriteLn;
  1773.     WrLblRect('      clipRgn', thePort^.clipRgn^^.rgnBBox);
  1774.     WriteLn;
  1775.     END;
  1776. {$ENDC}
  1777.